#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFile>
#include <QListWidget>
#include <QMenu>
#include <QDebug>
#include <cassert>
#include <QFileDialog>
#include <QScrollBar>
#include <QMessageBox>
#include <utility>
#include <exception>
#include <QFile>
#include <QTextStream>
#include "demotype.h"
#include <thread>

QMap<QString, bool> g_mapDatabaseTables;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    loadFlagA(false),
    loadFlagB(false),
    ds(nullptr)
{
    ui->setupUi(this);

    loadfileA = new QAction("load file 数据", this);
    loadfileB = new QAction("load file 失效数据", this);
    fileMenu = menuBar()->addMenu ("file");
    fileMenu->addAction(loadfileA);
    fileMenu->addAction(loadfileB);

    ui->queryType->insertItem (QueryType::LIKE, tr("模糊查询LIKE"));
    ui->queryType->setCurrentIndex (QueryType::LIKE);

    ui->querySelect->insertItem (0, tr("未使用的数据"));
    ui->querySelect->insertItem (1, tr("已经使用过的数据"));
    ui->querySelect->setCurrentIndex (0);
//    ui->querySelect->insertItem (0, tr("删除使用过的数据"));

    QObject::connect (loadfileA, SIGNAL(triggered(bool)), this, SLOT(loadA(bool)));
    QObject::connect (loadfileB, SIGNAL(triggered(bool)), this, SLOT(loadB(bool)));

    QObject::connect (ui->queryNumberFieldBtn, SIGNAL(clicked(bool)), this, SLOT(QueryAndOutPutNumberField(bool)));
    if(!ds){
        ds = DataServers::getInstance ();
        ds->load (g_dbName);
    }
    foreach (const QString& name, ds->getTablesName ()) {
        g_mapDatabaseTables.insert (name, true);
    }

    DemoType* pDemo = DemoType::create ();
    void *pElement = pDemo;
    DemoTypeHelper(pElement).get ();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::loadA (bool)
{
    QString filePath = QFileDialog::getOpenFileName(this,
                                                    tr("Open txt"), ".", tr("Data Files (*.txt)"));
    bool flag = loadFlagA.load ();
    if(flag == true){
        QMessageBox::question (this, tr("open file error!"), tr("Loading the selected Wen Bo."), QMessageBox::Ok);
        return;
    }
    if(dfB != filePath && dfA.load (filePath, 512))
    {
        GetFileDataProcessThread(&loadFlagA, std::move(dfA)
                                 , {[&](const QString& message){
                                                      ui->firsttxt->setText (message);
                                    }}
                                 , tr("正在加载数据文件....\n")
                                 , tr("等待导入数据库文件中....\n")
                                 , tr("正在导入数据库中....\n")
                                 , tr("导入成功....\n")
                                 ,  g_prefixUsedData
                                 ).detach ();

    }else{
        QMessageBox::question (this, tr("open file error!"), tr("The new file has been opened!\nPlease again!"), QMessageBox::Ok);
    }
}

void MainWindow::QueryAndOutPutNumberField(bool)
{

    QString filePath = QFileDialog::getSaveFileName (this, tr("Save file"), ".", tr("Data File(*.txt)"));

    QString inText = ui->queryNumberFieldLine->text ();
    if(inText.isEmpty ()){
        QMessageBox::question (this, tr("error"),tr("查询输入值不合法!"), QMessageBox::Ok);
        return;
    }

    bool ok;
    int numberField = inText.toInt (&ok);
    if(!ok){
        QMessageBox::question (this, tr("error"),tr("查询输入值不合法!不是数字."), QMessageBox::Ok);
        return;
    }else{
        if(numberField < 0){
            QMessageBox::question (this, tr("error"),tr("查询输入值不合法!\n不能为负数."), QMessageBox::Ok);
            return;
        }
    }

    QueryType type = (QueryType)(ui->queryType->currentIndex ());
    /////

    int nSelect = ui->querySelect->currentIndex ();
    const QString* SelectPrefix;
    switch(nSelect){
    case 0:
        SelectPrefix = &g_prefixNotUsedData;
        break;
    case 1:
        SelectPrefix = &g_prefixUsedData;
        break;
    }

    QString tableName = tr("%1%2").arg (*SelectPrefix).arg (numberField);

    QFile* pFile = new QFile(filePath);
    if (!pFile->open(QIODevice::WriteOnly | QIODevice::Text)){
        QMessageBox::question (this, tr("error"),tr("设置存储文件出错! \n请重试"), QMessageBox::Ok);
        SAFE_DEETE(pFile);
        return;
    }

    qDebug() << tableName;

    QStringList queryTables;

    for(auto begin = g_mapDatabaseTables.begin ();
        begin != g_mapDatabaseTables.end ();
        ++begin){
        QString key = begin.key ();
        if(key.indexOf (tableName) != -1)
            queryTables << key;
    }

    qDebug() << queryTables;

    if(queryTables.size () < 1){
        QMessageBox::question (this, tr("error"),tr("无法找到相应字段的数据! \n请重试"), QMessageBox::Ok);
        SAFE_DEETE(pFile);
        return;
    }

//    QSqlQuery query = ds->getQueryObj ();
//    std::thread t1([=](){
//        //LIKE ''123%
//        //= 136808080808
//        // in (...)
//        //not in(...)
//        QString sql = tr("SELECT phone FROM ? WHERE phone ?");
////        query.prepare ()
//        //        inText内容处理器=》产生sql语句我
//        //        query执行查询
//        //        pFile输出结果集


//        SAFE_DELETE_FILE(pFile);
//    });

//    t1.detach ();
//    QTextStream out(&fHandle);
}

void MainWindow::loadB (bool)
{
    QString filePath = QFileDialog::getOpenFileName(this,
                                                    tr("Open txt"), ".", tr("Data Files (*.txt)"));
    bool flag = loadFlagB.load ();
    if(flag == true){
        QMessageBox::question (this, tr("open file error!"), tr("Loading the selected Wen Bo."), QMessageBox::Ok);
        return;
    }
    if(linesB.valid ()){
        int status = QMessageBox::warning (this, tr("data exception!"), tr("exists data!\nDo you want to lose it?"), QMessageBox::Yes | QMessageBox::No);
        if(status == QMessageBox::No){
            return;
        }else{
            auto temp = std::move(linesB);
            ui->secondtxt->setText ("");
        }
    }
    if(dfA != filePath && dfB.load (filePath, 512))
    {
        GetFileDataProcessThread(&loadFlagB, std::move(dfB)
                                 , {[&](const QString& message){
                                                      ui->secondtxt->setText (message);
                                    }}
                                 ,tr("正在加载数据文件....\n")
                                 , tr("等待导入数据库文件中....\n")
                                 , tr("正在导入数据库中....\n")
                                 , tr("导入成功....\n")
                                 ,  g_prefixUsedData
                                 ).detach ();
    }else{
        QMessageBox::question (this, tr("open file error!"), tr("The new file has been opened!\nPlease again!"), QMessageBox::Ok);
    }
}

std::thread GetFileDataProcessThread(std::atomic_bool* loadFlag
                                            , DataFrame dfA
                                            , std::function<void(const QString&)> updateStatus
                                            , const QString& firstStatus
                                            , const QString& secondStatus
                                            , const QString& thirdStatus
                                            , const QString& lastStatus
                                            , const QString& prefixTable
                                            , const QString& sqlCreateTemplate
                                            , const QString& sqlInsertTempate
                                     )
{
    if(!dfA.isLoaded ())
        throw new std::runtime_error("File not loaded.");

    std::thread t1 = std::thread([=](DataFrame dfA){
            DataServers* ds = DataServers::getInstance ();
            QList<QString> notExistsTableName;
            QHash<QString, QVariantList> result, temp;
            try{
                updateStatus(firstStatus);
            }catch(std::exception e){
                qDebug() << e.what ();
            }

            if(loadFlag)
                loadFlag->store (true);
            do{
                    temp = dfA.get_chunk (-1, g_location);
                    for (QHash<QString, QVariantList>::iterator begin = temp.begin (); begin != temp.end (); ++begin) {
                        result[begin.key ()] << *begin;
                    }
            }while(temp.size () > 0);

            for(QString tName : result.keys ()){
                if(!g_mapDatabaseTables.contains (tName))
                    notExistsTableName.append (tName);
            }
            if(notExistsTableName.size () > 0){
                for(QString& begin : notExistsTableName){
                    QString sql = QString(sqlCreateTemplate)
                            .arg (prefixTable)
                            .arg (begin);
                    if(ds->query (sql).second){

                    }
                }
            }
            if(loadFlag)
                loadFlag->store (false);

            try{
                updateStatus(secondStatus);

                updateStatus(thirdStatus);
            }catch(std::exception e){
                qDebug() << e.what ();
            }

            for(QHash<QString, QVariantList>::iterator iter = result.begin (); iter != result.end (); ++iter){
                QSqlQuery query = ds->getQueryObj ();
                QString key = iter.key ();
                QString sql = QString (sqlInsertTempate)
                        .arg (prefixTable)
                        .arg (key);
                query.prepare (sql);
                query.addBindValue (*iter);

                if(ds->transaction ()){
                    if (!query.execBatch(QSqlQuery::BatchExecutionMode::ValuesAsColumns))
                        qDebug() << query.lastError();
                    ds->commit ();
                }
            }
            try{
                updateStatus(lastStatus);
            }catch(std::exception e){
                qDebug() << e.what ();
            }
    }, std::move(dfA));
    return t1;
}
